using System;
using System.IO;
using System.Drawing;
using System.Diagnostics;
using System.Resources;
using System.Collections;
using System.Windows.Forms;
using System.Globalization;
using System.ComponentModel;
using System.Drawing.Imaging;
using System.Drawing.Printing;
using System.Drawing.Drawing2D;
using System.Workflow.Interop;
using Microsoft.Win32;

namespace System.Workflow.ComponentModel.Design
{
    #region Class WorkflowPrintDocument
    // What did I do in this file:
    /// 1. Eliminated the synching of events OnBeginPrint and OnPrintPage as these can be overridden
    /// 2. Eliminated member variable firstpage as this can be deduced from the currentpage variable
    /// 3. Reorganized all the functions and bunched relavant functions togather
    /// 4. Eliminated the PageSetupDataChanged event.
    /// 5. Initialized all the member variables appropriately.
    /// 6. Eliminated unused functions and properties

    [ToolboxItem(false)]
    internal sealed class WorkflowPrintDocument : PrintDocument
    {
        #region Members and Constructor
        private WorkflowView workflowView = null;
        private PageSetupData pageSetupData = null;
        private PrintPreviewLayout previewLayout = null;

        //These are the temporary variables we calculate in PrepareToPrint
        private Point totalPrintablePages = Point.Empty; //number of pages in x and y
        private Point currentPrintablePage = Point.Empty; //page number (in the grid x,y)) we are printing right now
        private Point workflowAlignment = Point.Empty; //amount of alignment translation
        private float scaling; //1.0f is 100%
        private DateTime printTime; //when the document started to print
        private const int MaxHeaderFooterLines = 5; //maximum number of lines in header/footer

        public WorkflowPrintDocument(WorkflowView workflowView)//, IServiceProvider serviceProvider)
        {
            //this.serviceProvider = serviceProvider;
            this.pageSetupData = new PageSetupData();
            this.workflowView = workflowView;
            this.previewLayout = new PrintPreviewLayout(this.workflowView, this);
        }

        protected override void Dispose(bool disposing)
        {
            try
            {
                if (disposing)
                {
                    if (this.previewLayout != null)
                    {
                        this.previewLayout.Dispose();
                        this.previewLayout = null;
                    }
                }
            }
            finally
            {
                base.Dispose(disposing);
            }
        }
        #endregion

        #region Properties and Methods
        internal PrintPreviewLayout PrintPreviewLayout
        {
            get
            {
                return this.previewLayout;
            }
        }

        internal PageSetupData PageSetupData
        {
            get
            {
                return this.pageSetupData;
            }
        }
        #endregion

        #region Events and Overrides
        protected override void OnBeginPrint(PrintEventArgs printArgs)
        {
            base.OnBeginPrint(printArgs);

            this.currentPrintablePage = Point.Empty;

            //Validate the printer
            bool validPrinter = (PrinterSettings.IsValid &&
                                 PrinterSettings.InstalledPrinters.Count > 0 &&
                                 new ArrayList(PrinterSettings.InstalledPrinters).Contains(PrinterSettings.PrinterName));
            if (!validPrinter)
                DesignerHelpers.ShowError(this.workflowView, DR.GetString(DR.SelectedPrinterIsInvalidErrorMessage));

            printArgs.Cancel = (!validPrinter || this.workflowView.RootDesigner == null);
        }

        protected override void OnPrintPage(PrintPageEventArgs printPageArg)
        {
            base.OnPrintPage(printPageArg);

            AmbientTheme ambientTheme = WorkflowTheme.CurrentTheme.AmbientTheme;

            Graphics graphics = printPageArg.Graphics;
            graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
            graphics.SmoothingMode = SmoothingMode.HighQuality;

            //STEP1: We get the printer graphics only in the OnPrintPage function hence for layouting we need to call this function
            if (this.currentPrintablePage.IsEmpty)
                PrepareToPrint(printPageArg);

            //STEP2: GET ALL THE VALUES NEEDED FOR CALCULATION
            Margins hardMargins = GetHardMargins(graphics);
            Margins margins = new Margins(Math.Max(printPageArg.PageSettings.Margins.Left, hardMargins.Left),
                                          Math.Max(printPageArg.PageSettings.Margins.Right, hardMargins.Right),
                                          Math.Max(printPageArg.PageSettings.Margins.Top, hardMargins.Top),
                                          Math.Max(printPageArg.PageSettings.Margins.Bottom, hardMargins.Bottom));
            Size printableArea = new Size(printPageArg.PageBounds.Size.Width - (margins.Left + margins.Right), printPageArg.PageBounds.Size.Height - (margins.Top + margins.Bottom));
            Rectangle boundingRectangle = new Rectangle(margins.Left, margins.Top, printableArea.Width, printableArea.Height);
            Region clipRegion = new Region(boundingRectangle);

            try
            {
                graphics.TranslateTransform(-hardMargins.Left, -hardMargins.Top);
                graphics.FillRectangle(ambientTheme.BackgroundBrush, boundingRectangle);
                graphics.DrawRectangle(ambientTheme.ForegroundPen, boundingRectangle);

                //Draw the watermark image
                if (ambientTheme.WorkflowWatermarkImage != null)
                    ActivityDesignerPaint.DrawImage(graphics, ambientTheme.WorkflowWatermarkImage, boundingRectangle, new Rectangle(Point.Empty, ambientTheme.WorkflowWatermarkImage.Size), ambientTheme.WatermarkAlignment, AmbientTheme.WatermarkTransparency, false);

                Matrix oldTransform = graphics.Transform;
                Region oldClipRegion = graphics.Clip;
                graphics.Clip = clipRegion;
                graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;

                //STEP3: PRINT
                //Printer bitmap starts at the unprintable top left corner, hence, need to take it into account - move by the unprintable area:
                //Setup the translation and scaling for the page printing
                Point pageOffset = new Point(this.currentPrintablePage.X * printableArea.Width - this.workflowAlignment.X, this.currentPrintablePage.Y * printableArea.Height - this.workflowAlignment.Y);
                graphics.TranslateTransform(boundingRectangle.Left - pageOffset.X, boundingRectangle.Top - pageOffset.Y);
                graphics.ScaleTransform(this.scaling, this.scaling);

                //Calculate the viewport by reverse scaling the printable area size
                Size viewPortSize = Size.Empty;
                viewPortSize.Width = Convert.ToInt32(Math.Ceiling((float)printableArea.Width / this.scaling));
                viewPortSize.Height = Convert.ToInt32(Math.Ceiling((float)printableArea.Height / this.scaling));

                Point scaledAlignment = Point.Empty;
                scaledAlignment.X = Convert.ToInt32(Math.Ceiling((float)this.workflowAlignment.X / this.scaling));
                scaledAlignment.Y = Convert.ToInt32(Math.Ceiling((float)this.workflowAlignment.Y / this.scaling));

                Rectangle viewPort = new Rectangle(this.currentPrintablePage.X * viewPortSize.Width - scaledAlignment.X, this.currentPrintablePage.Y * viewPortSize.Height - scaledAlignment.Y, viewPortSize.Width, viewPortSize.Height);

                using (PaintEventArgs paintEventArgs = new PaintEventArgs(graphics, this.workflowView.RootDesigner.Bounds))
                {
                    ((IWorkflowDesignerMessageSink)this.workflowView.RootDesigner).OnPaint(paintEventArgs, viewPort);
                }

                graphics.Clip = oldClipRegion;
                graphics.Transform = oldTransform;

                //Now prepare the graphics for header footer printing
                HeaderFooterData headerFooterData = new HeaderFooterData();
                headerFooterData.Font = ambientTheme.Font;
                headerFooterData.PageBounds = printPageArg.PageBounds;
                headerFooterData.PageBoundsWithoutMargin = boundingRectangle;
                headerFooterData.HeaderFooterMargins = new Margins(0, 0, this.pageSetupData.HeaderMargin, this.pageSetupData.FooterMargin);
                headerFooterData.PrintTime = this.printTime;
                headerFooterData.CurrentPage = this.currentPrintablePage.X + this.currentPrintablePage.Y * this.totalPrintablePages.X + 1;
                headerFooterData.TotalPages = this.totalPrintablePages.X * this.totalPrintablePages.Y;
                headerFooterData.Scaling = this.scaling;
                WorkflowDesignerLoader serviceDesignerLoader = ((IServiceProvider)this.workflowView).GetService(typeof(WorkflowDesignerLoader)) as WorkflowDesignerLoader;
                headerFooterData.FileName = (serviceDesignerLoader != null) ? serviceDesignerLoader.FileName : String.Empty;

                //Print the header
                if (this.pageSetupData.HeaderTemplate.Length > 0)
                    PrintHeaderFooter(graphics, true, headerFooterData);

                //footer
                if (this.pageSetupData.FooterTemplate.Length > 0)
                    PrintHeaderFooter(graphics, false, headerFooterData);

                //are there more pages left?
                printPageArg.HasMorePages = MoveNextPage();
            }
            catch (Exception exception)
            {
                DesignerHelpers.ShowError(this.workflowView, DR.GetString(DR.SelectedPrinterIsInvalidErrorMessage) + "\n" + exception.Message);
                printPageArg.Cancel = true;
                printPageArg.HasMorePages = false;
            }
            finally
            {
                clipRegion.Dispose();
            }

            if (!printPageArg.HasMorePages)
                this.workflowView.PerformLayout(); //no more pages - redo regular layout using screen graphics
        }
        #endregion

        #region Helpers
        //Hard margins is part of the area the printer absolutely can not print onto. 
        //This area changes from printer to printer; CreateMeasurementGraphics creates appropriate DC 
        //for the selected printer
        internal Margins GetHardMargins(Graphics graphics)
        {
            IntPtr hDC = graphics.GetHdc();

            //Printer unit is hudredth of an inch hence convert the unprintable area from DPI to DPHI
            Point dpi = new Point(Math.Max(NativeMethods.GetDeviceCaps(hDC, NativeMethods.LOGPIXELSX), 1), Math.Max(NativeMethods.GetDeviceCaps(hDC, NativeMethods.LOGPIXELSY), 1));

            int printAreaHorz = (int)((float)NativeMethods.GetDeviceCaps(hDC, NativeMethods.HORZRES) * 100.0f / (float)dpi.X);
            int printAreaVert = (int)((float)NativeMethods.GetDeviceCaps(hDC, NativeMethods.VERTRES) * 100.0f / (float)dpi.Y);

            int physicalWidth = (int)((float)NativeMethods.GetDeviceCaps(hDC, NativeMethods.PHYSICALWIDTH) * 100.0f / (float)dpi.X);
            int physicalHeight = (int)((float)NativeMethods.GetDeviceCaps(hDC, NativeMethods.PHYSICALHEIGHT) * 100.0f / (float)dpi.Y);

            //margins in 1/100 inches
            int leftMargin = (int)((float)NativeMethods.GetDeviceCaps(hDC, NativeMethods.PHYSICALOFFSETX) * 100.0f / (float)dpi.X);
            int topMargin = (int)((float)NativeMethods.GetDeviceCaps(hDC, NativeMethods.PHYSICALOFFSETY) * 100.0f / (float)dpi.Y);
            int rightMargin = physicalWidth - printAreaHorz - leftMargin;
            int bottomMargin = physicalHeight - printAreaVert - topMargin;

            graphics.ReleaseHdc(hDC);

            return new Margins(leftMargin, rightMargin, topMargin, bottomMargin);
        }

        internal void PrintHeaderFooter(Graphics graphics, bool drawHeader, HeaderFooterData headerFooterPrintData)
        {
            //Format the header/footer
            string headerFooter = (drawHeader) ? this.pageSetupData.HeaderTemplate : this.pageSetupData.FooterTemplate;

            //these are the new format strings
            headerFooter = headerFooter.Replace("{#}", headerFooterPrintData.CurrentPage.ToString(CultureInfo.CurrentCulture));
            headerFooter = headerFooter.Replace("{##}", headerFooterPrintData.TotalPages.ToString(CultureInfo.CurrentCulture));
            headerFooter = headerFooter.Replace("{Date}", headerFooterPrintData.PrintTime.ToShortDateString());
            headerFooter = headerFooter.Replace("{Time}", headerFooterPrintData.PrintTime.ToShortTimeString());
            headerFooter = headerFooter.Replace("{FullFileName}", headerFooterPrintData.FileName);
            headerFooter = headerFooter.Replace("{FileName}", Path.GetFileName(headerFooterPrintData.FileName));
            headerFooter = headerFooter.Replace("{User}", SystemInformation.UserName);

            //limit the string to 5 lines of text max
            string[] headerFooterLines = headerFooter.Split(new char[] { '\n', '\r' }, MaxHeaderFooterLines + 1, StringSplitOptions.RemoveEmptyEntries);
            System.Text.StringBuilder text = new System.Text.StringBuilder();
            for (int i = 0; i < Math.Min(headerFooterLines.Length, MaxHeaderFooterLines); i++)
            {
                text.Append(headerFooterLines[i]);
                text.Append("\r\n");
            }
            headerFooter = text.ToString();

            //Measure the header /footer string
            Rectangle layoutRectangle = Rectangle.Empty;
            SizeF stringSize = graphics.MeasureString(headerFooter, headerFooterPrintData.Font);
            layoutRectangle.Size = new Size(Convert.ToInt32(Math.Ceiling((stringSize.Width))), Convert.ToInt32(Math.Ceiling((stringSize.Height))));
            layoutRectangle.Width = Math.Min(headerFooterPrintData.PageBoundsWithoutMargin.Width, layoutRectangle.Width);

            HorizontalAlignment alignment = (drawHeader) ? this.pageSetupData.HeaderAlignment : this.pageSetupData.FooterAlignment;
            StringFormat stringFormat = new StringFormat();
            stringFormat.Trimming = StringTrimming.EllipsisCharacter;
            switch (alignment)
            {
                case HorizontalAlignment.Left:
                    layoutRectangle.X = headerFooterPrintData.PageBoundsWithoutMargin.Left;
                    stringFormat.Alignment = StringAlignment.Near;
                    break;

                case HorizontalAlignment.Center:
                    layoutRectangle.X = headerFooterPrintData.PageBoundsWithoutMargin.Left + ((headerFooterPrintData.PageBoundsWithoutMargin.Width - layoutRectangle.Width) / 2); //align to the middle
                    stringFormat.Alignment = StringAlignment.Center;
                    break;

                case HorizontalAlignment.Right:
                    layoutRectangle.X = headerFooterPrintData.PageBoundsWithoutMargin.Left + (headerFooterPrintData.PageBoundsWithoutMargin.Width - layoutRectangle.Width); //align to the right corner
                    stringFormat.Alignment = StringAlignment.Far;
                    break;
            }

            //Align header footer vertically
            if (drawHeader)
            {
                layoutRectangle.Y = headerFooterPrintData.PageBounds.Top + headerFooterPrintData.HeaderFooterMargins.Top;
                stringFormat.LineAlignment = StringAlignment.Near;
            }
            else
            {
                layoutRectangle.Y = headerFooterPrintData.PageBounds.Bottom - headerFooterPrintData.HeaderFooterMargins.Bottom - layoutRectangle.Size.Height;
                stringFormat.LineAlignment = StringAlignment.Far;
            }

            //Draw header/footer string
            graphics.DrawString(headerFooter, headerFooterPrintData.Font, WorkflowTheme.CurrentTheme.AmbientTheme.ForegroundBrush, layoutRectangle, stringFormat);
        }

        private void PrepareToPrint(PrintPageEventArgs printPageArg)
        {
            Graphics graphics = printPageArg.Graphics;

            Size selectionSize = WorkflowTheme.CurrentTheme.AmbientTheme.SelectionSize;
            ((IWorkflowDesignerMessageSink)this.workflowView.RootDesigner).OnLayoutSize(graphics);
            ((IWorkflowDesignerMessageSink)this.workflowView.RootDesigner).OnLayoutPosition(graphics);
            this.workflowView.RootDesigner.Location = Point.Empty;

            //STEP2: Get the units needed for calculation
            Size rootDesignerSize = this.workflowView.RootDesigner.Size;
            rootDesignerSize.Width += 3 * selectionSize.Width;
            rootDesignerSize.Height += 3 * selectionSize.Height;

            Size paperSize = printPageArg.PageBounds.Size;
            Margins hardMargins = GetHardMargins(graphics);
            Margins margins = new Margins(Math.Max(printPageArg.PageSettings.Margins.Left, hardMargins.Left),
                                          Math.Max(printPageArg.PageSettings.Margins.Right, hardMargins.Right),
                                          Math.Max(printPageArg.PageSettings.Margins.Top, hardMargins.Top),
                                          Math.Max(printPageArg.PageSettings.Margins.Bottom, hardMargins.Bottom));
            Size printableArea = new Size(paperSize.Width - (margins.Left + margins.Right), paperSize.Height - (margins.Top + margins.Bottom));
            printableArea.Width = Math.Max(printableArea.Width, 1);
            printableArea.Height = Math.Max(printableArea.Height, 1);

            //STEP3: Calculate the scaling
            if (this.pageSetupData.AdjustToScaleFactor)
            {
                this.scaling = ((float)this.pageSetupData.ScaleFactor) / 100.0f;
            }
            else
            {
                float xScaling = (float)this.pageSetupData.PagesWide * (float)printableArea.Width / (float)rootDesignerSize.Width;
                float YScaling = (float)this.pageSetupData.PagesTall * (float)printableArea.Height / (float)rootDesignerSize.Height;

                this.scaling = Math.Min(xScaling, YScaling);
                //leave just 3 digital points (also, that will remove potential problems with ceiling e.g. when the number of pages would be 3.00000000001 we'll get 4)
                this.scaling = (float)(Math.Floor((double)this.scaling * 1000.0d) / 1000.0d);
            }

            //STEP4: Calculate the number of pages
            this.totalPrintablePages.X = Convert.ToInt32(Math.Ceiling((this.scaling * (float)rootDesignerSize.Width) / (float)printableArea.Width));
            this.totalPrintablePages.X = Math.Max(this.totalPrintablePages.X, 1);
            this.totalPrintablePages.Y = Convert.ToInt32(Math.Ceiling((this.scaling * (float)rootDesignerSize.Height) / (float)printableArea.Height));
            this.totalPrintablePages.Y = Math.Max(this.totalPrintablePages.Y, 1);

            //STEP5: Calculate the workflow alignment
            this.workflowAlignment = Point.Empty;

            if (this.pageSetupData.CenterHorizontally)
                this.workflowAlignment.X = (int)(((float)this.totalPrintablePages.X * (float)printableArea.Width / this.scaling - (float)rootDesignerSize.Width) / 2.0f * this.scaling);

            if (this.pageSetupData.CenterVertically)
                this.workflowAlignment.Y = (int)(((float)this.totalPrintablePages.Y * (float)printableArea.Height / this.scaling - (float)rootDesignerSize.Height) / 2.0f * this.scaling);

            this.workflowAlignment.X = Math.Max(this.workflowAlignment.X, selectionSize.Width + selectionSize.Width / 2);
            this.workflowAlignment.Y = Math.Max(this.workflowAlignment.Y, selectionSize.Height + selectionSize.Height / 2);

            //STEP6: Store other variables used
            this.printTime = DateTime.Now;
        }

        private bool MoveNextPage()
        {
            this.currentPrintablePage.X++;
            if (this.currentPrintablePage.X < this.totalPrintablePages.X)
                return true;

            //move to the next row
            this.currentPrintablePage.X = 0;
            this.currentPrintablePage.Y++;
            return (this.currentPrintablePage.Y < this.totalPrintablePages.Y);
        }

        internal sealed class HeaderFooterData
        {
            internal Font Font;
            internal Rectangle PageBounds;
            internal Rectangle PageBoundsWithoutMargin;
            internal Margins HeaderFooterMargins;
            internal DateTime PrintTime;
            internal int CurrentPage;
            internal int TotalPages;
            internal float Scaling;
            internal string FileName;
        }
        #endregion
    }
    #endregion

    #region Class PageSetupData
    internal sealed class PageSetupData
    {
        #region Members and Constructors
        internal static readonly int DefaultScaleFactor = 100;
        internal static readonly int DefaultMinScaleFactor = 10;
        internal static readonly int DefaultMaxScaleFactor = 400;
        internal static readonly int DefaultPages = 1;
        internal static readonly int DefaultHeaderMargin = 50;
        internal static readonly int DefaultFooterMargin = 50;

        private Margins margins = null;
        private bool landscape = false;
        private int headerMargin = PageSetupData.DefaultHeaderMargin;
        private int footerMargin = PageSetupData.DefaultFooterMargin;
        private string headerTemplate = string.Empty;
        private string footerTemplate = string.Empty;
        private HorizontalAlignment headerAlignment = HorizontalAlignment.Center;
        private HorizontalAlignment footerAlignment = HorizontalAlignment.Center;
        private bool adjustToScaleFactor = true;
        private int scaleFactor = PageSetupData.DefaultScaleFactor;
        private int pagesWide = PageSetupData.DefaultPages;
        private int pagesTall = PageSetupData.DefaultPages;
        private bool centerHorizontally = false;
        private bool centerVertically = false;
        private bool headerCustom = false;
        private bool footerCustom = false;

        private static readonly string WinOEPrintingSubKey = DesignerHelpers.DesignerPerUserRegistryKey + "\\Printing";
        private const string RegistryHeaderTemplate = "HeaderTemplate";
        private const string RegistryHeaderMarging = "HeaderMargin";
        private const string RegistryHeaderCustom = "HeaderCustom";
        private const string RegistryHeaderAlignment = "HeaderAlignment";
        private const string RegistryFooterTemplate = "FooterTemplate";
        private const string RegistryFooterMarging = "FooterMargin";
        private const string RegistryFooterCustom = "FooterCustom";
        private const string RegistryFooterAlignment = "FooterAlignment";
        private const string RegistryCenterHorizontally = "CenterHorizontally";
        private const string RegistryCenterVertically = "CenterVertically";

        internal PageSetupData()
        {
            RegistryKey key = Registry.CurrentUser.OpenSubKey(WinOEPrintingSubKey);
            if (null != key)
            {
                try
                {
                    object registryValue = null;

                    registryValue = key.GetValue(RegistryHeaderAlignment);
                    if (null != registryValue && registryValue is int) this.headerAlignment = (HorizontalAlignment)registryValue;

                    registryValue = key.GetValue(RegistryFooterAlignment);
                    if (null != registryValue && registryValue is int) this.footerAlignment = (HorizontalAlignment)registryValue;

                    registryValue = key.GetValue(RegistryHeaderMarging);
                    if (null != registryValue && registryValue is int) this.headerMargin = (int)registryValue;

                    registryValue = key.GetValue(RegistryFooterMarging);
                    if (null != registryValue && registryValue is int) this.footerMargin = (int)registryValue;

                    registryValue = key.GetValue(RegistryHeaderTemplate);
                    if (null != registryValue && registryValue is string) this.headerTemplate = (string)registryValue;

                    registryValue = key.GetValue(RegistryFooterTemplate);
                    if (null != registryValue && registryValue is string) this.footerTemplate = (string)registryValue;

                    registryValue = key.GetValue(RegistryHeaderCustom);
                    if (null != registryValue && registryValue is int) this.headerCustom = Convert.ToBoolean((int)registryValue);

                    registryValue = key.GetValue(RegistryFooterCustom);
                    if (null != registryValue && registryValue is int) this.footerCustom = Convert.ToBoolean((int)registryValue);

                    registryValue = key.GetValue(RegistryCenterHorizontally);
                    if (null != registryValue && registryValue is int) this.centerHorizontally = Convert.ToBoolean((int)registryValue);

                    registryValue = key.GetValue(RegistryCenterVertically);
                    if (null != registryValue && registryValue is int) this.centerVertically = Convert.ToBoolean((int)registryValue);
                }
                finally
                {
                    key.Close();
                }
            }

            PrinterSettings printerSettings = new PrinterSettings();
            this.landscape = printerSettings.DefaultPageSettings.Landscape;
            this.margins = printerSettings.DefaultPageSettings.Margins;
        }

        public void StorePropertiesToRegistry()
        {
            RegistryKey key = Registry.CurrentUser.CreateSubKey(WinOEPrintingSubKey);
            if (null != key)
            {
                try
                {
                    key.SetValue(RegistryHeaderAlignment, (int)this.headerAlignment);
                    key.SetValue(RegistryFooterAlignment, (int)this.footerAlignment);
                    key.SetValue(RegistryHeaderMarging, this.headerMargin);
                    key.SetValue(RegistryFooterMarging, this.footerMargin);
                    key.SetValue(RegistryHeaderTemplate, this.headerTemplate);
                    key.SetValue(RegistryFooterTemplate, this.footerTemplate);
                    key.SetValue(RegistryHeaderCustom, Convert.ToInt32(this.headerCustom));
                    key.SetValue(RegistryFooterCustom, Convert.ToInt32(this.footerCustom));
                    key.SetValue(RegistryCenterHorizontally, Convert.ToInt32(this.centerHorizontally));
                    key.SetValue(RegistryCenterVertically, Convert.ToInt32(this.centerVertically));
                }
                finally
                {
                    key.Close();
                }
            }
        }
        #endregion

        #region Properties and Methods
        public bool Landscape
        {
            get { return this.landscape; }
            set { this.landscape = value; }
        }
        public bool AdjustToScaleFactor
        {
            get { return this.adjustToScaleFactor; }
            set { this.adjustToScaleFactor = value; }
        }
        public int ScaleFactor
        {
            get { return this.scaleFactor; }
            set
            {
                if (value >= PageSetupData.DefaultMinScaleFactor && value <= PageSetupData.DefaultMaxScaleFactor)
                    this.scaleFactor = value;
            }
        }
        public int PagesWide
        {
            get { return this.pagesWide < 1 ? 1 : this.pagesWide; }
            set
            {
                if (value > 0)
                    this.pagesWide = value;
            }
        }
        public int PagesTall
        {
            get { return this.pagesTall < 1 ? 1 : this.pagesTall; }
            set
            {
                if (value > 0)
                    this.pagesTall = value;
            }
        }
        public Margins Margins
        {
            get { return this.margins; }
            set { this.margins = value; }
        }
        public int HeaderMargin
        {
            get { return this.headerMargin; }
            set
            {
                if (value >= 0)
                    this.headerMargin = value;
            }
        }
        public int FooterMargin
        {
            get { return this.footerMargin; }
            set
            {
                if (value >= 0)
                    this.footerMargin = value;
            }
        }
        public string HeaderTemplate
        {
            get { return this.headerTemplate; }
            set { this.headerTemplate = value; }
        }
        public string FooterTemplate
        {
            get { return this.footerTemplate; }
            set { this.footerTemplate = value; }
        }
        public HorizontalAlignment HeaderAlignment
        {
            get { return this.headerAlignment; }
            set { this.headerAlignment = value; }
        }
        public HorizontalAlignment FooterAlignment
        {
            get { return this.footerAlignment; }
            set { this.footerAlignment = value; }
        }
        public bool HeaderCustom
        {
            get { return this.headerCustom; }
            set { this.headerCustom = value; }
        }
        public bool FooterCustom
        {
            get { return this.footerCustom; }
            set { this.footerCustom = value; }
        }
        public bool CenterHorizontally
        {
            get { return this.centerHorizontally; }
            set { this.centerHorizontally = value; }
        }
        public bool CenterVertically
        {
            get { return this.centerVertically; }
            set { this.centerVertically = value; }
        }
        #endregion
    }
    #endregion
}
